using System;

namespace ScrewTurn.Wiki.PluginFramework
{
    /// <summary>
    /// It is the interface that the ScrewTurn Wiki's Host object implements.
    /// </summary>
    public interface IHost
    {
        /// <summary>
        /// Gets the list of the Users.
        /// </summary>
        UserInfo[] AllUsers { get; }

        /// <summary>
        /// Gets the list of the Pages.
        /// </summary>
        PageInfo[] AllPages { get; }

        /// <summary>
        /// Gets the list of the Categories.
        /// </summary>
        CategoryInfo[] AllCategories { get; }

        /// <summary>
        /// Gets the list of Snippets.
        /// </summary>
        Snippet[] AllSnippets { get; }

        /// <summary>
        /// Gets the list of Navigation Paths.
        /// </summary>
        NavigationPath[] AllNavigationPaths { get; }

        /// <summary>
        /// Gets the values of the Wiki Settings.
        /// </summary>
        /// <param name="name">The Setting's Name.</param>
        /// <returns>The Setting's value.</returns>
        string GetSettingValue(SettingName name);

        /// <summary>
        /// Finds a user by username, properly handling Users Storage Providers.
        /// </summary>
        /// <param name="username">The username.</param>
        /// <returns>The <see cref="T:UserInfo" />, or <b>null</b> if no users are found.</returns>
        UserInfo FindUser(string username);

        /// <summary>
        /// Gets the Categories of a Page.
        /// </summary>
        /// <param name="page">The Page.</param>
        /// <returns>The Categories.</returns>
        CategoryInfo[] GetCategoriesPerPage(PageInfo page);

        /// <summary>
        /// Gets the WikiPage with the specified Name, or null.
        /// </summary>
        /// <param name="name">The Name of the Page.</param>
        /// <returns>The Wiki Page, or null.</returns>
        PageInfo FindPage(string name);

        /// <summary>
        /// Gets the Content of a Page.
        /// </summary>
        /// <param name="page">The Page.</param>
        /// <returns>The Page Content.</returns>
        PageContent GetPageContent(PageInfo page);

        /// <summary>
        /// Gets the Backup/Revision numbers of a Page.
        /// </summary>
        /// <param name="page">The Page.</param>
        /// <returns>The Backup/Revision numbers.</returns>
        int[] GetBackups(PageInfo page);

        /// <summary>
        /// Gets the Content of a Page Backup.
        /// </summary>
        /// <param name="page">The Page.</param>
        /// <param name="revision">The revision.</param>
        /// <returns>The Backup Content.</returns>
        PageContent GetBackupContent(PageInfo page, int revision);

        /// <summary>
        /// Gets the formatted content of a Page, retrieving it from the cache (if available).
        /// </summary>
        /// <param name="page">The Page.</param>
        /// <returns>The formatted content of the Page.</returns>
        string GetFormattedContent(PageInfo page);

        /// <summary>
        /// Formats a block of WikiMarkup, using the built-in formatter only.
        /// </summary>
        /// <param name="raw">The block of WikiMarkup.</param>
        /// <returns>The formatted content.</returns>
        string Format(string raw);

        /// <summary>
        /// Sends an Email.
        /// </summary>
        /// <param name="recipient">The Recipient Email address.</param>
        /// <param name="sender">The Sender's Email address.</param>
        /// <param name="subject">The Subject.</param>
        /// <param name="body">The Body.</param>
        /// <param name="html">True if the message is HTML.</param>
        /// <returns>True if the message has been sent successfully.</returns>
        bool SendEmail(string recipient, string sender, string subject, string body, bool html);

        /// <summary>
        /// Logs a new message.
        /// </summary>
        /// <param name="message">The Message.</param>
        /// <param name="entryType">The Entry Type.</param>
        /// <param name="caller">The Component that calls the method. The caller cannot be null.</param>
        void LogEntry(string message, LogEntryType entryType, object caller);

        /// <summary>
        /// Reads a text file.
        /// </summary>
        /// <param name="filename">The filename.</param>
        /// <returns>The content of the file.</returns>
        string ReadFile(string filename);

        /// <summary>
        /// Writes a text file.
        /// </summary>
        /// <param name="filename">The filename.</param>
        /// <param name="content">The content.</param>
        /// <returns>True if the file is written.</returns>
        bool WriteFile(string filename, string content);

        /// <summary>
        /// Aligns a Date and Time object to the User's Time Zone preferences.
        /// </summary>
        /// <param name="dt">The Date/Time to align.</param>
        /// <returns>The aligned Date/Time.</returns>
        /// <remarks>The method takes care of daylight saving settings.</remarks>
        DateTime AlignDateTimeWithPreferences(DateTime dt);

        /// <summary>
        /// Forces to reload a list of items.
        /// </summary>
        /// <param name="list">The list to Reload.</param>
        /// <param name="caller">The Component that calls the method. The caller cannot be null.</param>
        void RequestRefresh(RefreshList list, object caller);

        /// <summary>
        /// Clears the cache.
        /// </summary>
        /// <param name="data">The part of the cache to clear.</param>
        void ClearCache(CacheData data);

        /// <summary>
        /// Adds an item in the Editing Toolbar.
        /// </summary>
        /// <param name="item">The item to add.</param>
        /// <param name="text">The text of the item.</param>
        /// <param name="value">The value of the item: if <b>item</b> is <b>ToolbarItem.SpecialTagWrap</b>, separate start and end tag with a pipe.</param>
        void AddToolbarItem(ToolbarItem item, string text, string value);

        /// <summary>
        /// Event fired whenever an activity is performed on a User Account.
        /// </summary>
        event EventHandler<UserAccountActivityEventArgs> UserAccountActivity;

        /// <summary>
        /// Even fired whenever an activity is performed on a Page.
        /// </summary>
        event EventHandler<PageActivityEventArgs> PageActivity;
    }

    /// <summary>
    /// Contains arguments for User Account Activity events.
    /// </summary>
    public class UserAccountActivityEventArgs : EventArgs
    {
        private readonly UserAccountActivity activity;
        private readonly UserInfo user;

        /// <summary>
        /// Initializes a new instance of the <b>UserAccountActivityEventArgs</b> class.
        /// </summary>
        /// <param name="user">The User Info the activity refers to.</param>
        /// <param name="activity">The activity performed.</param>
        public UserAccountActivityEventArgs(UserInfo user, UserAccountActivity activity)
        {
            this.user = user;
            this.activity = activity;
        }

        /// <summary>
        /// Gets the user the activity refers to.
        /// </summary>
        public UserInfo User
        {
            get { return user; }
        }

        /// <summary>
        /// Gets the activity performed.
        /// </summary>
        public UserAccountActivity Activity
        {
            get { return activity; }
        }
    }

    /// <summary>
    /// Lists legal User Account Activity types.
    /// </summary>
    public enum UserAccountActivity
    {
        /// <summary>
        /// A user account has been added.
        /// </summary>
        AccountAdded,
        /// <summary>
        /// A user account has been activated.
        /// </summary>
        AccountActivated,
        /// <summary>
        /// A user account has been deactivated.
        /// </summary>
        AccountDeactivated,
        /// <summary>
        /// A user account has been promoted to administrator.
        /// </summary>
        AccountPromoted,
        /// <summary>
        /// A user account has been downgraded to normal user.
        /// </summary>
        AccountDowngraded,
        /// <summary>
        /// A user account has been modified (email, password).
        /// </summary>
        AccountModified,
        /// <summary>
        /// A user account has been removed.
        /// </summary>
        AccountRemoved
    }

    /// <summary>
    /// Contains arguments for Page Activity events.
    /// </summary>
    public class PageActivityEventArgs : EventArgs
    {
        private readonly PageActivity activity;
        private readonly string author;
        private readonly PageInfo page;

        /// <summary>
        /// Initializes a new instance of the <b>PageActivityEventArgs</b> class.
        /// </summary>
        /// <param name="page">The page the activity refers to.</param>
        /// <param name="author">The author of the activity, if available, <b>null</b> otherwise.</param>
        /// <param name="activity">The activity.</param>
        public PageActivityEventArgs(PageInfo page, string author, PageActivity activity)
        {
            this.page = page;
            this.author = author;
            this.activity = activity;
        }

        /// <summary>
        /// Gets the page the activity refers to.
        /// </summary>
        public PageInfo Page
        {
            get { return page; }
        }

        /// <summary>
        /// Gets the author of the activity.
        /// </summary>
        public string Author
        {
            get { return author; }
        }

        /// <summary>
        /// Gets the activity.
        /// </summary>
        public PageActivity Activity
        {
            get { return activity; }
        }
    }

    /// <summary>
    /// Lists legal Page Activity types.
    /// </summary>
    public enum PageActivity
    {
        /// <summary>
        /// A page has been created.
        /// </summary>
        PageCreated,
        /// <summary>
        /// A page has been modified.
        /// </summary>
        PageModified,
        /// <summary>
        /// A page has been renamed.
        /// </summary>
        PageRenamed,
        /// <summary>
        /// A page has been rolled back.
        /// </summary>
        PageRolledBack,
        /// <summary>
        /// A page's backups have been deleted.
        /// </summary>
        PageBackupsDeleted,
        /// <summary>
        /// A page's status has been changed.
        /// </summary>
        PageStatusChanged,
        /// <summary>
        /// A page has been deleted.
        /// </summary>
        PageDeleted,
        /// <summary>
        /// A message has been posted to a page discussion.
        /// </summary>
        MessagePosted,
        /// <summary>
        /// A message has been modified.
        /// </summary>
        MessageModified,
        /// <summary>
        /// A message has been deleted from a page discussion.
        /// </summary>
        MessageDeleted
    }

    /// <summary>
    /// Enumerates the Types of Log Entries.
    /// </summary>
    public enum LogEntryType
    {
        /// <summary>
        /// Represents a simple Message.
        /// </summary>
        General,
        /// <summary>
        /// Represents a Warning.
        /// </summary>
        Warning,
        /// <summary>
        /// Represents an Error.
        /// </summary>
        Error
    }

    /// <summary>
    /// Enumerates the Setting values' names.
    /// </summary>
    public enum SettingName
    {
        /// <summary>
        /// The Title of the Wiki.
        /// </summary>
        WikiTitle,
        /// <summary>
        /// The Main URL of the Wiki.
        /// </summary>
        MainUrl,
        /// <summary>
        /// The current Theme Name.
        /// </summary>
        Theme,
        /// <summary>
        /// The Contact Email.
        /// </summary>
        ContactEmail,
        /// <summary>
        /// The Sender Email.
        /// </summary>
        SenderEmail,
        /// <summary>
        /// The current Theme relative path (URL).
        /// </summary>
        ThemePath,
        /// <summary>
        /// The Name of the default Page.
        /// </summary>
        DefaultPage,
        /// <summary>
        /// The Date/Time format.
        /// </summary>
        DateTimeFormat,
        /// <summary>
        /// The default Language (for example <b>en-US</b>).
        /// </summary>
        DefaultLanguage,
        /// <summary>
        /// The default Time Zone (a string representing the shift in <b>minutes</b> respect to the Greenwich time, for example <b>-120</b>).
        /// </summary>
        DefaultTimeZone,
        /// <summary>
        /// The Wiki Access status (<b>PRIVATE</b>, <b>NORMAL</b>, <b>PUBLIC</b>).
        /// </summary>
        AccessStatus,
        /// <summary>
        /// The Themes directory.
        /// </summary>
        ThemesDirectory,
        /// <summary>
        /// The Public directory.
        /// </summary>
        PublicDirectory,
        /// <summary>
        /// The Messages directory.
        /// </summary>
        MessagesDirectory,
        /// <summary>
        /// The Pages directory.
        /// </summary>
        PagesDirectory,
        /// <summary>
        /// The Plugins directory.
        /// </summary>
        PluginsDirectory,
        /// <summary>
        /// The Snippets directory.
        /// </summary>
        SnippetsDirectory,
        /// <summary>
        /// The Temp directory.
        /// </summary>
        TempDirectory,
        /// <summary>
        /// The Upload directory.
        /// </summary>
        UploadDirectory,
        /// <summary>
        /// A value (true/false) indicating whether users can create new pages.
        /// </summary>
        UsersCanCreateNewPages,
        /// <summary>
        /// A value (true/false) indicating whether users can create new categories.
        /// </summary>
        UsersCanCreateNewCategories,
        /// <summary>
        /// A value (true/false) indicating whether users can create delete files.
        /// </summary>
        UsersCanDeleteFiles,
        /// <summary>
        /// A value (true/false) indicating whether users can manage page categories.
        /// </summary>
        UsersCanManageCategories,
        /// <summary>
        /// A value (true/false) indicating whether users can create new accounts.
        /// </summary>
        UsersCanRegister,
        /// <summary>
        /// A value (true/false) indicating whether users can upload files.
        /// </summary>
        UsersCanUploadFiles,
        /// <summary>
        /// A value (true/false) indicating whether users can view uploaded files.
        /// </summary>
        UsersCanViewFiles,
        /// <summary>
        /// The regex used to validate usernames.
        /// </summary>
        UsernameRegex,
        /// <summary>
        /// The regex used to validate passwords.
        /// </summary>
        PasswordRegex,
        /// <summary>
        /// The regex used to validate email addresses.
        /// </summary>
        EmailRegex,
        /// <summary>
        /// The regex used to validate the main Wiki URL.
        /// </summary>
        MainUrlRegex,
        /// <summary>
        /// A value (true/false) indicating whether to activate page editing with a double click.
        /// </summary>
        EnableDoubleClickEditing,
        /// <summary>
        /// A value (true/false) indicating whether to process single line breaks in WikiMarkup.
        /// </summary>
        ProcessSingleLineBreaks,
        /// <summary>
        /// The account activation mode.
        /// </summary>
        AccountActivationMode,
        /// <summary>
        /// The file types allowed for upload.
        /// </summary>
        AllowedFileTypes,
        /// <summary>
        /// A value (true/false) indicating whether the configuration tab is visible to administrators other than the built-in 'admin'.
        /// </summary>
        ConfigVisibleToAdmins,
        /// <summary>
        /// A value (true/false) indicating whether to disable the automatic version check.
        /// </summary>
        DisableAutomaticVersionCheck,
        /// <summary>
        /// A value (true/false) indicating whether to disable the breadcrumbs trail.
        /// </summary>
        DisableBreadcrumbsTrail,
        /// <summary>
        /// A value (true/false) indicating whether to disable the page cache.
        /// </summary>
        DisableCache,
        /// <summary>
        /// A value (true/false) indicating whether to disable the captcha control in public functionalities.
        /// </summary>
        DisableCaptchaControl,
        /// <summary>
        /// A value (true/false) indicating whether to disable concurrent page editing.
        /// </summary>
        DisableConcurrentEditing,
        /// <summary>
        /// The page discussion permissions.
        /// </summary>
        DiscussionPermissions,
        /// <summary>
        /// A value (true/false) indicating whether to enable HTTP compression.
        /// </summary>
        EnableHttpCompression,
        /// <summary>
        /// A value (true/false) indicating whether to enable View State compression.
        /// </summary>
        EnableViewStateCompression,
        /// <summary>
        /// The number of file access tries.
        /// </summary>
        FileAccessTries,
        /// <summary>
        /// The delay between failed file access tries (milliseconds).
        /// </summary>
        FileAccessTryDelay,
        /// <summary>
        /// A value (true/false) indicating whether to file management is allowed to anonymous users when the Wiki is in Public Access mode.
        /// </summary>
        FileManagementInPublicAccessAllowed,
        /// <summary>
        /// The logging level.
        /// </summary>
        LoggingLevel,
        /// <summary>
        /// The max size for uploaded files (bytes).
        /// </summary>
        MaxFileSize,
        /// <summary>
        /// The extension used for pages.
        /// </summary>
        PageExtension,
        /// <summary>
        /// A value (true/false) indicating whether to SCRIPT tags are allowed in WikiMarkup.
        /// </summary>
        ScriptTagsAllowed,
        /// <summary>
        /// The version of the Wiki Engine.
        /// </summary>
        WikiVersion,
    }

    /// <summary>
    /// Enumerates the refreshable Lists.
    /// </summary>
    public enum RefreshList
    {
        /// <summary>
        /// The Users list.
        /// </summary>
        Users,
        /// <summary>
        /// The Pages list.
        /// </summary>
        Pages
    }

    /// <summary>
    /// Enumerates the parts of the cache that can be cleared.
    /// </summary>
    public enum CacheData
    {
        /// <summary>
        /// All the pages data.
        /// </summary>
        Pages,
        /// <summary>
        /// All the meta-files (Header, Footer, Sidebar, etc.).
        /// </summary>
        MetaFiles
    }

    /// <summary>
    /// Enumerates the toolbar items that can be added.
    /// </summary>
    [Serializable]
    public enum ToolbarItem
    {
        /// <summary>
        /// A Special Tag that is inserted in the text.
        /// </summary>
        SpecialTag,
        /// <summary>
        /// A special tag that wraps the selected text.
        /// </summary>
        SpecialTagWrap
    }
}